import cv
from math import sqrt, fabs
import os.path
#import abc #overkill?

#try:
#    import rtmidi
#except ImportError, msg:
#    print "rtmidi could not be imported. Cause : %s"%msg

class Pad(object):
    def __init__(self, x, y, width, height):
        # because  a square isn't always perfectly drawn we have
        # different width/height
        self.x = x
        self.y = y
        self.w = width
        self.h = height
    
    def __repr__(self):
        return "PAD at (%d, %d) w:%d h:%d"%(self.x, self.y,
                                            self.w, self.h)
    
    def draw(self, img):
        """ draw himself on a 3 channels img """
        cv.Rectangle(img, (self.x, self.y), (self.x+self.w, self.y+self.h),
                     (255, 0, 0), 3)

class Slider(object):
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.w = width
        self.h = height
    
    def __repr__(self):
        return "SLIDER at (%d, %d) w:%d h:%d"%(self.x, self.y,
                                            self.w, self.h)
    
    def draw(self, img):
        """ draw himself on a 3 channels img """
        cv.Rectangle(img, (self.x, self.y), (self.x+self.w, self.y+self.h),
                     (0, 0, 255), 3)

class Knob(object):
    def __init__(self, centerX, centerY, radius):
        self.centerX = centerX
        self.centerY = centerY
        self.radius = radius
    
    def __str__(self):
        return "KNOB at (%d, %d) radius:%d"%(self.centerX, self.centerY,
                                            self.radius)
    
    def draw(self, img):
        """ draw himself on a 3 channels img """
        cv.Circle(img, (self.centerX, self.centerY), self.radius, (0, 255, 0), 3)

def getPads(img):
    """ get the pads on a grayscale image """
    cascade_name = os.path.join("haar_learning", "pad", "pad_cascade.xml")
    cascade = cv.Load(cascade_name)

    pads = cv.HaarDetectObjects(img, cascade, cv.CreateMemStorage(0))
    if pads:
        return [Pad(x, y, w, h) for (x,y,w,h),n in pads]
    
    return None

def getSliders(img):
    """ get the sliders on a grayscale image """
    cascade_name = os.path.join("haar_learning", "slider", "slider_cascade.xml")
    cascade = cv.Load(cascade_name)

    sliders = cv.HaarDetectObjects(img, cascade, cv.CreateMemStorage(0))
    if sliders:
        return [Slider(x, y, w, h) for (x,y,w,h),n in sliders]
    
    return None

def getKnobs(img):
    """ get the knobs on a grayscale image """
    cascade_name = os.path.join("haar_learning", "knob", "knob_cascade.xml")
    cascade = cv.Load(cascade_name)

    knobs = cv.HaarDetectObjects(img, cascade, cv.CreateMemStorage(0))
    if knobs:
        return [Knob(x+(w/2), y+(h/2), w/2) for (x,y,w,h),n in knobs]
    
    return None

if __name__=="__main__":
    cv.NamedWindow("cam")
    cv.NamedWindow("grey")
    cv.NamedWindow("virtual controller")
    
    #capture = cv.CaptureFromCAM(0)
    #frame = cv.QueryFrame(capture)
    #for test purposes
    frame = cv.LoadImage("controller.jpg")
    frameW = frame.width
    frameH = frame.height
    
    grey = cv.CreateImage((frameW, frameH), 8, 1)
    cv.SetZero(grey)
    
    #while True:
    if True:
        cv.CvtColor(frame, grey, cv.CV_BGR2GRAY)
        #cv.AdaptiveThreshold(grey, grey, 150)
        cv.ShowImage("cam", frame)
        cv.ShowImage("grey", grey)
        
        virtualImage = cv.CreateImage((frameW, frameH), 8, 3)
        cv.SetZero(virtualImage)
        
        knobs = getKnobs(grey)
        if knobs:
            print "%d knobs detected"%len(knobs)
            for knob in knobs:
                knob.draw(virtualImage)
        else:
            print "no knobs were detected"

        
        pads = getPads(grey)
        if pads:
            print "%d pads detected"%len(pads)
            for pad in pads:
                pad.draw(virtualImage)
        else:
            print "no pads were detected"
            
        sliders = getSliders(grey)
        if sliders:
            print "%d sliders detected"%len(sliders)
            for slider in sliders:
                slider.draw(virtualImage)
        else:
            print "no sliders were detected"
        
        cv.ShowImage("virtual controller", virtualImage)
        
        cv.WaitKey(0)